package vip.meeet;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import vip.meeet.utils.ESUtil;
import vip.meeet.utils.HttpUtil;

import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

/**
 * curl -H 'Content-Type:application/json' -d '{"query":{"match_all":{}}}' http://host:port/index/_search?scroll=10m&search_type=scan
 */
public final class ScrollHelper {

    private String hostPort;
    private String index;
    private String time;
    private volatile String currentScrollId;
    private volatile boolean started;
    private volatile boolean done;

    private static final String urlBase = "http://%s/%s/_search?scroll=%s&search_type=scan";
//    String urlBase = "http://%s/%s/_search?scroll=%s";

    public ScrollHelper(String hostPort, String index, String time) {
        this.hostPort = hostPort;
        this.index = index;
        this.time = time;
    }

    public Optional<List<JSONObject>> getData() throws IOException {
        if(done){
            return Optional.empty();
        }
        if(started){
            return startScroll();
        }else {
            return scrollWithId();
        }
    }

    private Optional<List<JSONObject>> startScroll() throws IOException {
        started = true;
        String url = String.format(urlBase, hostPort, index, time);
        String content = HttpUtil.postJsonContent(url, defaultScrollBody());
        return dealScrollBody(content);
    }

    private static String defaultScrollBody(){
        JSONObject body = new JSONObject();
        JSONObject matchAllBody = new JSONObject();
        matchAllBody.put("match_all",new JSONObject());
        body.put("query",matchAllBody);
        body.put("sort","[\"_doc\"]");//避免排序
        body.put("size",1000);//@TODO 根据索引大小和数量估算文档大小
        return body.toJSONString();
    }

    private Optional<List<JSONObject>> scrollWithId() throws IOException {
        String urlBase = "http://%s/_search/scroll";
        String url = String.format(urlBase, hostPort);
        String scrollRequestBody = ESUtil.scrollRequestBody(currentScrollId, time);
        String result = HttpUtil.postJsonContent(url, scrollRequestBody);
        return dealScrollBody(result);
    }


    public static void deleteScroll(String hostPort,List<String> scrollIds) throws IOException {
        String ids = String.join(",", scrollIds);
        String urlBase = "http://%s/_search?scroll/%s";
        String url = String.format(urlBase, hostPort,ids);
        HttpUtil.delete(url);
    }

    private Optional<List<JSONObject>> dealScrollBody(String scrollBody) throws IOException {
        JSONObject result = JSON.parseObject(scrollBody);
        LinkedList<JSONObject> results = new LinkedList<>();
        currentScrollId = result.getString("_scroll_id");
        JSONObject hitsObject = result.getJSONObject("hits");
        JSONArray hits = hitsObject.getJSONArray("hits");
        if(hits.size() == 0){
            done = true;
            if(currentScrollId != null) {//结束删除scrollId
                deleteScroll(hostPort, Arrays.asList(currentScrollId));
            }
            return Optional.empty();
        }
        for(Object jsonObject : hits){
            JSONObject rs = (JSONObject) jsonObject;
            JSONObject source = rs.getJSONObject("_source");
            results.add(source);
        }
        return Optional.ofNullable(results);
    }


}
